package com.googlecode.groovy_toy_orm
/**
 * @author: DavydovMD
 * Date: 12.04.13
 * Time: 11:31
 */
class Unmarshaller<T> implements DbSourced<T> {
    Mapper mapper

    Class<T> defaultBeanClass

    Unmarshaller(Mapper mapper, Class defaultBeanClass) {
        this.mapper = mapper
        this.defaultBeanClass = defaultBeanClass
    }

    Unmarshaller(MultiTableMapper<T> mapper) {
        this.mapper = mapper
        this.defaultBeanClass = mapper.beanClass
    }

    private class NastyWorkaround {}

    @Override
    public T updateFromDb(T bean, String fieldName, def value) {
        assert fieldName != null
        assert bean.getClass().isAssignableFrom(defaultBeanClass)

        if (value instanceof NastyWorkaround) {
            value = bean."${fieldName}"
        }

        Map row = queryBuilder().allFields().where().and(fieldName, ConditionOp.EQ, value).build().firstRowRaw()

        mapper.updateFrom(row, bean, queryBuilder().columnAliases) as T
    }

    @Override
    public T updateFromDb(T bean, String fieldName) {
        updateFromDb(bean, fieldName, new NastyWorkaround())
    }

    @Override
    public T updateFromDb(T bean) {
        updateFromDb(bean, mapper.getKeyField(), queryBuilder().columnAliases)
    }

    @Override
    def T buildFromDb(def value, String fieldName) {
        Map row = queryBuilder().allFields().where().and(fieldName, ConditionOp.EQ, value).build().firstRowRaw()
        if (!row) throw new NoSuchElementException("Your query returned no result: ${fieldName} = ${value} ")
        mapper.buildFrom(row, defaultBeanClass, queryBuilder().getColumnAliases()) as T
    }

    @Override
    def T buildFromDb(def value) {
        buildFromDb(value, mapper.keyField)
    }

    @Override
    /**
     * Looks weird, need to refactor
     */
    def QueryBuilder queryBuilder() {
        if (mapper instanceof SingleDbTableMapper) {
            return new SingleDbQueryBuilder(mapper, defaultBeanClass)
        }

        if (mapper instanceof MultiTableMapper) {
            if (mapper.isMultiDb()) {
                throw new UnsupportedOperationException("Not implemented!")
                //return new MultiDbQueryBuilder(mapper as MultiTableMapper)
            } else {
                return new SingleDbQueryBuilder(mapper)
            }

        }

        throw new IllegalStateException("Invalid mapper (expected: MultiTableMapper or SingleDbTableMapper but was: ${mapper}")
    }
}
